Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Maj tracés réseaux #929

Merged
merged 10 commits into from
Nov 18, 2024
Merged

Maj tracés réseaux #929

merged 10 commits into from
Nov 18, 2024

Conversation

totakoko
Copy link
Member

@totakoko totakoko commented Nov 14, 2024

Cette PR introduit quelques scripts utilisés pour mettre à jour les tracés et les données. Pas mal de synchro postgres - airtable.
Il y aura encore peut-être des changements pour affiner le processus avec les futures mises à jour côté Sébastien.
Le but était de vraiment maitriser les changements faits et noter toutes les modifications. Finalement c'était un peu un bourbier et il y a des choses que j'aurais pu simplifier.

  • j'ai encore plein de requêtes à mettre en forme / transformer en CLI.

Pour déployer en prod (à faire à peu près pendant le déploiement du build...) :

./scripts/copyLocalTableToRemote.sh prod reseaux_de_chaleur
./scripts/copyLocalTableToRemote.sh prod reseaux_de_froid
./scripts/copyLocalTableToRemote.sh prod zone_de_developpement_prioritaire
./scripts/copyLocalTableToRemote.sh prod zones_et_reseaux_en_construction

./scripts/copyLocalTableToRemote.sh prod reseaux_de_chaleur_tiles --data-only
./scripts/copyLocalTableToRemote.sh prod reseaux_de_froid_tiles --data-only
./scripts/copyLocalTableToRemote.sh prod zone_de_developpement_prioritaire_tiles --data-only
./scripts/copyLocalTableToRemote.sh prod zones_et_reseaux_en_construction_tiles --data-only

+ bonus avec la diminution de la hauteur du logo, vu avec Antoine et Florence

\"energie_ratio_autreChaleurRecuperee\",
\"energie_ratio_biogaz\"
) as \"energie_max_ratio\"
*
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A un moment donné, on avait besoin de l'énergie majoritaire, mais ce n'est plus le cas, donc on simplifie la requête.

@@ -15,7 +15,7 @@
3. Mise à jour des données sur les réseaux depuis Airtable
- Si la table des réseaux a été mise à jour lors de l'étape précédente : `yarn cli update-networks network`
- Sinon
- `yarn cli download-network network`
- `yarn cli download-update-network network`
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

J'ai changé un peu le processus, et je voulais que download-network (= synchro de airtable vers postgres) n'ait pas d'effets de bord et ne modifie pas airtable. J'ai donc changé la commande référencée ici.
Ca devrait bouger aussi un peu à l'avenir.

.argument('[zoomMin]', 'Minimum zoom', parseInt, 0)
.argument('[zoomMax]', 'Maximum zoom', parseInt, 17)
.argument('[zoomMin]', 'Minimum zoom', (v) => parseInt(v), 0)
.argument('[zoomMax]', 'Maximum zoom', (v) => parseInt(v), 17)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

En fait il n'y a pas que v qui est passé en argument et ça passait directement en 2e argument de parseInt comme base. Et on veut pas ça...

} catch (err) {
console.error('err', err);
process.exit(2);
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je pensais qu'il y avait un catch global pour chaque action mais que nenni. Il faudrait que ça soit global pour pas s'embêter avec des try catch.

@@ -11,7 +11,7 @@ table=$2
options=$3
if [[ $env != "dev" && $env != "prod" ]]; then
usage
exit 1+
exit 1
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo d'origine 👏

@@ -48,7 +48,7 @@ const conversionConfigReseauxDeChaleur = {
'Dev_reseau%': TypeNumber,
'Rend%': TypeNumber,
reseaux_techniques: TypeBool,
departement: TypeNumber,
departement: TypeString,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

La colonne departement contenait jusque là des codes départements / codes postaux. Et ça contient maintenant des labels... Du coup j'ai changé le type, et il faudra dans le futur compléter cette information automatiquement. C'est utilisé que côté airtable.

@@ -525,7 +525,7 @@ export function buildMapLayers(config: MapConfiguration): MapSourceLayersSpecifi
source: {
type: 'vector',
tiles: [`${location.origin}/api/map/zoneDP/{z}/{x}/{y}`],
maxzoom: tileSourcesMaxZoom,
maxzoom: 14,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changé car pas besoin d'avoir des cases plus petites. (qui prennent aussi du temps à être générées)

ST_Transform('SRID=4326;POINT(${lon} ${lat})'::geometry, 2154),
geom
)
`)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bon j'ai pas mal galéré aussi avec ça. Globalement le cast <boolean> est important pour kysely. Mais après j'ai dû utiliser sql.raw car je m'en sortais pas avec l'erreur bind message supplies 2 parameters, but prepared statement "" requires 0

@totakoko totakoko marked this pull request as ready for review November 18, 2024 12:12
Copy link
Collaborator

@martinratinaud martinratinaud left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

J'ai regardé (un peu légèrement c'est vrai :-)) mais la logique me parait bonne et la gestion facile à comprendre et à modifier, donc bravo !

@@ -32,7 +32,7 @@ const conversionConfigReseauxDeChaleur = {
'reseaux classes': TypeBool,
has_PDP: TypeBool,
nom_reseau: TypeString,
communes: TypeStringToArray,
// communes: TypeStringToArray,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Peut etre a enlever si on ne s'en sert plus

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comme c'est pas le seul champ, je préfère laisser pour le moment (voir toujours), pour bien comprendre qu'on a plein de champs définis mais qu'on ne veut pas synchroniser celui-là et que ce n'est pas un oubli.

table: table,
count: networksAirtable.length,
});
const startTime = Date.now();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on peut utilise logger.time et logger.timeEnd je pense

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

time et timeEnd sont disponibles sur l'objet console uniquement. Là c'est un logger winston (json par défaut), et j'ai pas vu de méthodes similaires.

@@ -45,11 +47,18 @@ program
await downloadNetwork(table);
});

program
.command('download-update-network')
.argument('<network-id>', 'Network id', validateNetworkId)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

petite description ici serait bien genre "download AND updates" d'ailleurs, je changerais le nom de la fonction qui peut porter à conusion (downloadUpdated)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pour la partie updated, c'est plutôt un update que ça fait car ça met à jour aussi airtable. A la base, le but était de synchroniser que dans un sens airtable => postgres. Le processus a été modifié pour mettre à jour aussi des choses côté airtable. J'aurais plus vu une commande différente.

Avec le processus que j'ai fait, les mises à jour postgres => airtable n'utilisent que les changements de géométrie et mettent à jour les lignes correspondantes côté airtable.

Et à côté, on a la synchro airtable => postgres pour regarder les métadonnées quand potentiellement ça a pu être modifié sur airtable.

Donc au final, c'est un peu deprecated, et ça devrait sans doute partir avec les futures mises à jour des tracés (quand je process sera affiné et 100% fonctionnel). En attendant je met un downloadAndUpdate pour être plus clair.

'changement',
'ign_communes',
db.raw('geom_new as geom'),
db.raw("st_geometrytype(geom_new) = 'ST_MultiLineString' as is_line"), // spécifique mais un peu commun quand même
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol 🤣 c'est everridé dans quel cas ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sur les 4 types de données, on utilise cette info dans 2 cas (rdc, rdf), et on devrait utiliser ces informations dans 3 cas (+ futurs réseaux).

return !globalDryRun ? query : Promise.resolve();
}

function logAirtableQuery(operation: 'create', table: AirtableTable, data: object): Promise<any>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pas vraiment fan de ces fonctions qui sont en fait uniquement typescript

On peut les mettres dans un fichier.d.ts ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perso, je trouve largement plus intéressant d'avoir la définition de fonction à côté de son implémentation. Il y a moins de risques d'oublier de la mettre à jour.

Là le but était d'avoir du polymorphisme pour appeler une seule fonction (qui accepte tous les arguments).

Après pour l'usage de fichiers .d.ts, pour moi c'est pas utile sachant que tout le projet est en .ts, donc plutôt que de mettre certains types dans du .d.ts et d'autres dans du .ts, je préfère tout mettre en .ts. Par contre, bien sûr rien n'empêche d'extraire les types et interfaces dans leur propre fichiers.


// fonctions utilitaires pour logger les requêtes

function logPGQuery(query: Knex.QueryBuilder<any, number>): Promise<any> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

de manière générale je mettrais ces utilitaires dans scripts/networks/utils car c'est déjà assez gros comme fichier

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pk pas, après se retrouver avec un fichier util, c'est pas forcément génial :p

De base, surtout quand le code est tout nouveau ou je ne suis pas sûr qu'il va rester très longtemps dans cet état, je préfère rester simple en termes de fichiers plutôt que l'exploser en plusieurs.
Là dans le fichier, c'est surtout la config qui prend de la place.
Mais on pourrait mettre ça dans un fichier airtable-operations.ts ou qqch comme ça.

*/
export const syncPostgresToAirtable = async (dryRun: boolean) => {
const startTime = Date.now();
parentLogger.info('start postgres to airtable synchronization');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pareil, possibilité d'utiliser time et timeEnd

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Justement, a priori non. :/

Copy link
Member Author

@totakoko totakoko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merci pour les commentaires. J'ai répondu à tous. Il y a pas mal de points à améliorer qui se feront petit à petit je pense, notamment l'organisation des fichiers, la suppression des commandes obsolètes, l'utilisation de kysely ❤️ ... pour avoir un process beaucoup plus clair et automatique.

J'ai pris en compte le download-and-update, et pour le reste on en reparle !

@@ -45,11 +47,18 @@ program
await downloadNetwork(table);
});

program
.command('download-update-network')
.argument('<network-id>', 'Network id', validateNetworkId)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pour la partie updated, c'est plutôt un update que ça fait car ça met à jour aussi airtable. A la base, le but était de synchroniser que dans un sens airtable => postgres. Le processus a été modifié pour mettre à jour aussi des choses côté airtable. J'aurais plus vu une commande différente.

Avec le processus que j'ai fait, les mises à jour postgres => airtable n'utilisent que les changements de géométrie et mettent à jour les lignes correspondantes côté airtable.

Et à côté, on a la synchro airtable => postgres pour regarder les métadonnées quand potentiellement ça a pu être modifié sur airtable.

Donc au final, c'est un peu deprecated, et ça devrait sans doute partir avec les futures mises à jour des tracés (quand je process sera affiné et 100% fonctionnel). En attendant je met un downloadAndUpdate pour être plus clair.

table: table,
count: networksAirtable.length,
});
const startTime = Date.now();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

time et timeEnd sont disponibles sur l'objet console uniquement. Là c'est un logger winston (json par défaut), et j'ai pas vu de méthodes similaires.

'changement',
'ign_communes',
db.raw('geom_new as geom'),
db.raw("st_geometrytype(geom_new) = 'ST_MultiLineString' as is_line"), // spécifique mais un peu commun quand même
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sur les 4 types de données, on utilise cette info dans 2 cas (rdc, rdf), et on devrait utiliser ces informations dans 3 cas (+ futurs réseaux).

return !globalDryRun ? query : Promise.resolve();
}

function logAirtableQuery(operation: 'create', table: AirtableTable, data: object): Promise<any>;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perso, je trouve largement plus intéressant d'avoir la définition de fonction à côté de son implémentation. Il y a moins de risques d'oublier de la mettre à jour.

Là le but était d'avoir du polymorphisme pour appeler une seule fonction (qui accepte tous les arguments).

Après pour l'usage de fichiers .d.ts, pour moi c'est pas utile sachant que tout le projet est en .ts, donc plutôt que de mettre certains types dans du .d.ts et d'autres dans du .ts, je préfère tout mettre en .ts. Par contre, bien sûr rien n'empêche d'extraire les types et interfaces dans leur propre fichiers.

*/
export const syncPostgresToAirtable = async (dryRun: boolean) => {
const startTime = Date.now();
parentLogger.info('start postgres to airtable synchronization');
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Justement, a priori non. :/


// fonctions utilitaires pour logger les requêtes

function logPGQuery(query: Knex.QueryBuilder<any, number>): Promise<any> {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pk pas, après se retrouver avec un fichier util, c'est pas forcément génial :p

De base, surtout quand le code est tout nouveau ou je ne suis pas sûr qu'il va rester très longtemps dans cet état, je préfère rester simple en termes de fichiers plutôt que l'exploser en plusieurs.
Là dans le fichier, c'est surtout la config qui prend de la place.
Mais on pourrait mettre ça dans un fichier airtable-operations.ts ou qqch comme ça.

@@ -32,7 +32,7 @@ const conversionConfigReseauxDeChaleur = {
'reseaux classes': TypeBool,
has_PDP: TypeBool,
nom_reseau: TypeString,
communes: TypeStringToArray,
// communes: TypeStringToArray,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comme c'est pas le seul champ, je préfère laisser pour le moment (voir toujours), pour bien comprendre qu'on a plein de champs définis mais qu'on ne veut pas synchroniser celui-là et que ce n'est pas un oubli.

@totakoko totakoko merged commit 3eb73a0 into dev Nov 18, 2024
4 of 5 checks passed
@totakoko totakoko deleted the maj_tracés_réseaux branch November 18, 2024 15:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants